package com.atguigu.c_designed.m2stucturalModel.s4Composite;

import java.util.ArrayList;
import java.util.List;

/**
 * 又名部分整体模式，是用于把一组相似的对象当作一个单一的对象。
 * 组合模式依据树形结构来组合对象，用来表示部分以及整体层次。这种类型的设计模式属于结构型模式，它创建了对象组的树形结构。
 */

/**
 * 组合模式主要包含三种角色：
 *
 * - 抽象根节点（Component）：定义系统各层次对象的共有方法和属性，可以预先定义一些默认行为和属性。
 * - 树枝节点（Composite）：定义树枝节点的行为，存储子节点，组合树枝节点和叶子节点形成一个树形结构。
 * - 叶子节点（Leaf）：叶子节点对象，其下再无分支，是系统层次遍历的最小单位。
 */
public class CompositeClient {

    public static void main(String[] args) {
        MenuComposite menuComposite = new Menu("文件夹1",1);
        menuComposite.add(new Menu("文件1",2));
        menuComposite.add(new Menu("文件2",2));
        menuComposite.add(new Menu("文件3",2));
        menuComposite.add(new Menu("文件4",2));
        menuComposite.add(new Menu("文件夹1-1",2));
        menuComposite.add(new MenuItem("文件1-1",3));
        menuComposite.print();
    }
    /**
     * 优点
     *
     * - 组合模式可以清楚地定义分层次的复杂对象，表示对象的全部或部分层次，它让客户端忽略了层次的差异，方便对整个层次结构进行控制。
     * - 客户端可以一致地使用一个组合结构或其中单个对象，不必关心处理的是单个对象还是整个组合结构，简化了客户端代码。
     * - 在组合模式中增加新的树枝节点和叶子节点都很方便，无须对现有类库进行任何修改，符合“开闭原则”。
     * - 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案，通过叶子节点和树枝节点的递归组合，可以形成复杂的树形结构，但对树形结构的控制却非常简单。
     */

}

abstract class MenuComposite{
    protected String name;
    protected int level;

    public MenuComposite(String name, int level) {
        this.name = name;
        this.level = level;
    }

    public void add(MenuComposite menuComposite){
        throw new UnsupportedOperationException("不支持的操作");
    }

    public void remove(MenuComposite menuComposite){
        throw new UnsupportedOperationException("不支持的操作");
    }
    public MenuComposite getChild(int i){
        throw new UnsupportedOperationException("不支持的操作");
    }

    public String getName() {
        return name;
    }
    public void print(){
        throw new UnsupportedOperationException();
    }
}

class Menu extends MenuComposite{

    List<MenuComposite> menus = new ArrayList<>();

    public Menu(String name, int level) {
        super(name,level);
    }

    @Override
    public void add(MenuComposite menuComposite) {
        menus.add(menuComposite);
    }

    @Override
    public void remove(MenuComposite menuComposite) {
        menus.remove(menuComposite);
    }

    @Override
    public MenuComposite getChild(int i) {
        return menus.get(i);
    }

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public void print() {
        for (int i = 1; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);
        for (MenuComposite menuComponent : menus) {
            menuComponent.print();
        }
    }
}
class MenuItem extends MenuComposite{

    public MenuItem(String name, int level) {
        super(name,level);
    }

    @Override
    public void print() {
        for (int i = 1; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);
    }
}